package com.helloniu.red5;

import java.util.ArrayList;

import org.red5.io.amf3.ByteArray;
import org.red5.io.utils.ObjectMap;
import org.red5.server.Scope;
import org.red5.server.adapter.ApplicationAdapter;
import org.red5.server.api.IClient;
import org.red5.server.api.IConnection;
import org.red5.server.api.IScope;
import org.red5.server.api.Red5;
import org.red5.server.api.so.ISharedObject;

import com.helloniu.red5.adm.BussinessManager;
import com.helloniu.red5.adm.ConferenceManager;
import com.helloniu.red5.info.BussinessUnit;
import com.helloniu.red5.info.ConferenceInfo;

public class AbsWebHandler extends ApplicationAdapter {
    private String usersSO = "UsersSO";
    private String userKey = "HN_USER_KEY";

   @Override
    public boolean roomStart(IScope room) {
        Tool.o("room start:" + room.getName() +"|"+ room.getDepth());
        boolean result = super.roomStart(room);
        ISharedObject so = getSharedObject(room, usersSO);

        if(so == null) {
            createSharedObject(room, usersSO, false);
        }
        
        //add a conf to conf manager
        try {
        	ConferenceManager.getInstance().addConference(room.getName());
        }
        catch(Exception ex) {
        	Tool.o(ex);
        	ex.printStackTrace();
        }

        return result;
    }

    @Override
    public void roomStop(IScope room) {
        Tool.o("roomStop:" + room.getName() +"|"+ room.getDepth());
        //remove a conf to conf manager
    	ConferenceManager.getInstance().removeConference(room.getName());
        super.roomStop(room);
    }

    /*
    @Override   
    public void roomLeave(IClient client, IScope room) {
        super.roomLeave(client, room);
        
        Tool.o("roomleave:" + client  +"|"+ room.getName() +"|"+client.getAttribute(userKey));      
    }
    */
    
    // must use leave , room leave fall down
    @Override
    public void leave(IClient client, IScope room) {
        super.leave(client, room);
        
        if(room instanceof Scope && room.getDepth() == 2) {
            Tool.o("leave:" + room.getClass() +"|"+ room.getDepth()+"|"+ room.getName() +"|"+client.getAttribute(userKey));
            ISharedObject so = getSharedObject(room, usersSO);
            so.setAttribute("SomeoneLeave", client.getAttribute(userKey));  
            String confID = scope.getName();
        	// userlist
            String userID = (String) client.getAttribute(userKey);
        	ConferenceManager.getInstance().getConference(confID).removeUser(userID);
        }
        
        // remove a user
    }

    // ---flex called---
    // fl_funcName    
    public void fl_ClientJoin(String userID) {
        IConnection conn = Red5.getConnectionLocal();
      
        // @temp tonyy
        if(!Tool.isValidName(userID)) {
            conn.close();
            return;
        }

        IClient curClient = conn.getClient();
        curClient.setAttribute(userKey, userID);
        
        IScope scope = conn.getScope();
        Tool.o("fl_ClientJoin:" +"|"+ userID +"|"+ curClient +"|"+ scope.getName() +"|"+ scope.getDepth());
        
        
        int depth = scope.getDepth();
        if(scope instanceof Scope && depth == 2) {
        	String confID = scope.getName();
        	// @temp tonyy, sometimes add 2 times? why???
        	// userlist
        	Tool.o("add user");
        	if(ConferenceManager.getInstance().getConference(confID).getUser(userID) == null) {
        		ConferenceManager.getInstance().getConference(confID).addUser(userID);	
        	}
        	else {
        		Tool.o("add user --error found!");	
        	}
        	
        	
        }
        
        // add a user to conf
        // 
        /*
        int depth = scope.getDepth();
        if(scope instanceof Scope && depth == 2) {
            ISharedObject so = getSharedObject(scope, usersSO);            
            so.setAttribute("someoneJoin", userID);
        }
        */
    }
    
    public void fl_DrawShape(Object shape) {
    	Tool.o("=====draw shape=:" + shape +"|"+ (shape instanceof ObjectMap));
    	if(shape instanceof ObjectMap) {
    		BussinessManager.getInstance().addShape((ObjectMap) shape);	
    	}    
    }
    
    public void fl_ChangeShape(Object shape) {
    	Tool.o("=====change shape=:" + shape +"|"+ (shape instanceof ObjectMap));
    	if(shape instanceof ObjectMap) {
    		BussinessManager.getInstance().changeShape((ObjectMap) shape);	
    	}
    }
    
    public ArrayList fl_getShapeList() {
    	return BussinessManager.getInstance().shapeList;    	
    }
    
    public void fl_ClientUpdate(ByteArray bunit) {
        IConnection conn = Red5.getConnectionLocal();

        IClient curClient = conn.getClient();
        String userID = (String) curClient.getAttribute(userKey);
        
// @temp tonyy
        if(!Tool.isValidName(userID)) {
            conn.close();
            return;
        }
        
        Tool.o("fl_ClientUpdate:" +"|"+ userID +"|"+ curClient);        
        
        IScope scope = conn.getScope();
                
        int depth = scope.getDepth();
        
        if(scope instanceof Scope && depth == 2) {
        	String confID = scope.getName();
        	// userlist
        	ConferenceInfo cinfo = 
        		ConferenceManager.getInstance().getConference(confID);
        	
        	// cinfo.userList --> bytearray
        	BussinessUnit bussiUnit = new BussinessUnit();
        	bunit.position(0);
        	bussiUnit.parseData(bunit);
        	
        	cinfo.updateUser(userID, bussiUnit);
        	Tool.o("fl_ClientUpdate:"  + cinfo +"|"+ bussiUnit);
        }
        
        
    }

    public ArrayList fl_getUserlist() {        
        IConnection conn = Red5.getConnectionLocal();
        IScope scope = conn.getScope();
        Tool.o("fl_getUserlist:"  + scope);        
        int depth = scope.getDepth();
        if(scope instanceof Scope && depth == 2) {
        	String confID = scope.getName();
        	// userlist
        	ConferenceInfo cinfo = 
        		ConferenceManager.getInstance().getConference(confID);
        	
        	Tool.o("======fl_getUserlist======:" + cinfo +"|"+ cinfo.userList);
        	// cinfo.userList --> bytearray
        	
        	int length = cinfo.userList.size();
        	ArrayList<ByteArray> nlist = new ArrayList<ByteArray>();
        	
        	for(int i = 0; i < length; i++) {
        		ByteArray e = new ByteArray();
        		cinfo.userList.get(i).writeData(e);
        		Tool.o("======fl_getUserlist======:" + i +"|"+ cinfo.userList.get(i));	
        		nlist.add(e);
        	}
        	
        	return nlist;
        }
        
        
        
        ArrayList<String> list = new ArrayList<String>();
        return list;
    }
}
